package com.mini.grpc.loadbalance;

import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 轮询负载均衡器实现
 * 按照轮询方式依次选择服务端地址
 * 
 * @author Mini-gRPC
 */
public class RoundRobinLoadBalancer implements LoadBalancer {
    
    private static final String NAME = "round_robin";
    
    private volatile List<SocketAddress> addresses = Collections.emptyList();
    private final AtomicInteger index = new AtomicInteger(0);
    private final AtomicBoolean shutdown = new AtomicBoolean(false);
    
    /**
     * 默认构造函数
     */
    public RoundRobinLoadBalancer() {
    }
    
    /**
     * 构造函数，初始化地址列表
     * 
     * @param addresses 初始地址列表
     */
    public RoundRobinLoadBalancer(List<SocketAddress> addresses) {
        updateAddresses(addresses);
    }
    
    @Override
    public SocketAddress choose() {
        if (shutdown.get()) {
            return null;
        }
        
        List<SocketAddress> currentAddresses = addresses;
        if (currentAddresses.isEmpty()) {
            return null;
        }
        
        // 使用原子操作确保线程安全的轮询
        int currentIndex = index.getAndIncrement();
        // 防止整数溢出
        if (currentIndex < 0) {
            index.set(0);
            currentIndex = 0;
        }
        
        return currentAddresses.get(currentIndex % currentAddresses.size());
    }
    
    @Override
    public void updateAddresses(List<SocketAddress> addresses) {
        if (shutdown.get()) {
            return;
        }
        
        if (addresses == null) {
            this.addresses = Collections.emptyList();
        } else {
            // 创建不可变副本
            this.addresses = Collections.unmodifiableList(new ArrayList<>(addresses));
        }
        
        // 重置索引
        index.set(0);
    }
    
    @Override
    public List<SocketAddress> getAddresses() {
        return addresses;
    }
    
    @Override
    public String getName() {
        return NAME;
    }
    
    @Override
    public void shutdown() {
        shutdown.set(true);
        addresses = Collections.emptyList();
    }
    
    @Override
    public boolean isShutdown() {
        return shutdown.get();
    }
    
    @Override
    public String toString() {
        return "RoundRobinLoadBalancer{" +
                "name=" + NAME +
                ", addresses=" + addresses.size() +
                ", currentIndex=" + index.get() +
                ", shutdown=" + shutdown.get() +
                '}';
    }
} 